#include <QDebug>
#include "PynotoWindow.h"
#include "Include/Project.h"
#include "Include/IconProvider.h"
#include "Include/Settings.h"
#include "ui_PynotoWindow.h"
#include "Include/IEditorsManager.h"
#include "Include/IProjectManager.h"
#include "Include/IConsole.h"

PynotoWindow::PynotoWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::PynotoWindow),
    _projectManager(NULL),
    _editors(NULL)
{
    ui->setupUi(this);
    setWindowIcon(QIcon(":/pynoto.svgz"));
    setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
    loadPlugins();

    QStringList recent = Plugins::Settings::instance()->recentProjects();
    foreach(QString prj, recent){
        QFileInfo info(prj);
        if (!info.exists())
            continue;

        QAction *action = new QAction(info.filePath(), this);
        action->setData(prj);
        setAction(action, SLOT(openProject()));
        ui->menuOpenRecent->addAction(action);
    }

    setAction(_projectManager, ui->actionOpenProject, SLOT(openProject()), "project-open");
    setAction(_projectManager, ui->actionClosePoject, SLOT(closeProject()), "project-close");
    setAction(_projectManager, ui->actionProjectProperties, SLOT(projectProperties()), "configure");
    setAction(_projectManager, ui->actionFindInProject, SLOT(findInProject()), "edit-find-project");
    setAction(ui->actionPreferences, SLOT(showPreferences()), "configure");
    setAction(_projectManager, ui->actionNewProject, SLOT(newProject()), "project-new");
    setAction(this, ui->actionRun, SLOT(projectRun()), "project-run");

    connect(_projectManager, SIGNAL(projectAvailable(bool)), ui->actionClosePoject, SLOT(setEnabled(bool)));
    connect(_projectManager, SIGNAL(projectAvailable(bool)), ui->actionFindInProject, SLOT(setEnabled(bool)));
    connect(_projectManager, SIGNAL(projectAvailable(bool)), ui->actionProjectProperties, SLOT(setEnabled(bool)));
    connect(_projectManager, SIGNAL(openFile(const QString&, int, bool)), _editors, SLOT(openEditor(const QString&, int, bool)));

    QAction *reset = new QAction(this);
    reset->setShortcut(Qt::Key_Escape);
    connect(reset, SIGNAL(triggered()), _editors, SLOT(resetEditor()));
    addAction(reset);

    if (Plugins::Settings::instance()->lastOpenedProject() != "")
        _projectManager.slot("loadProject", Q_ARG(QString, Plugins::Settings::instance()->lastOpenedProject()));
}


PynotoWindow::~PynotoWindow()
{
    delete _editors;
    delete _projectManager;
    delete ui;
}

void PynotoWindow::loadPlugins()
{
    setupProjectManager();
    setupEditors();
}

void PynotoWindow::setupProjectManager()
{
    _projectManager = loadPlugin<Plugins::IProjectManager>("libproject-manager.so");
    connect(_projectManager, SIGNAL(projectAvailable(bool)), SLOT(onProjectAvailable(bool)));
    ui->leftDock->setWidget(_projectManager);
    connect(ui->bottomDoc->consoleWindow(), SIGNAL(fileNavigate(QString, int)), _projectManager, SLOT(navigateFileLine(QString, int)));
}

void PynotoWindow::setupEditors()
{
    _editors = loadPlugin<Plugins::IEditorsManager>("libeditors.so");

    QWidget *wid = new QWidget(this);
    wid->setLayout(new QVBoxLayout());
    wid->layout()->setContentsMargins(0, 0, 0, 0);
    wid->layout()->addWidget(_editors->widget());
    BottomDockTitleWidget *title = new BottomDockTitleWidget(this);
    connect(title, SIGNAL(modeSelected(DockShowMode)), ui->bottomDoc, SLOT(modeSelected(DockShowMode)));
    connect(ui->bottomDoc, SIGNAL(dockModeSelected(DockShowMode)), title, SLOT(dockModeSelected(DockShowMode)));
    wid->layout()->addWidget(title);
    setCentralWidget(wid);

    ui->openedDocs->setWidget(_editors->openedDocsWidget());

    connect(ui->bottomDoc, SIGNAL(jimpCurrentFileLine(int)), _editors, SLOT(jimpCurrentFileLine(int)));

    connect(_editors, SIGNAL(undoAvailable(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(redoAvailable(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionCopy, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionCut, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionDelete, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(pasteAvailable(bool)), ui->actionPaste, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionUppercase, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionLowercase, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(copyAvailable(bool)), ui->actionCapitalize, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(modifyChanged(bool)), ui->actionSave, SLOT(setEnabled(bool)));

    connect(_editors, SIGNAL(activated(QString)), _projectManager, SLOT(fileActivated(QString)));
    connect(_editors, SIGNAL(fileNavigate(QString, int)), _projectManager, SLOT(navigateFile(QString, int)));
    connect(_editors, SIGNAL(errorListChanged(QAbstractTableModel*)), ui->bottomDoc, SLOT(errorListChanged(QAbstractTableModel*)));
    connect(_editors, SIGNAL(modifyChanged(QString, bool)), _projectManager, SLOT(modifyChanged(QString, bool)));

    connect(_editors, SIGNAL(findAvailable(bool)), ui->actionFindNext, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(findAvailable(bool)), ui->actionFindPrevious, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(replaceAvailable(bool)), ui->actionReplace, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(replaceAvailable(bool)), ui->actionReplaceFind, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(replaceAvailable(bool)), ui->actionReplaceFindPrevious, SLOT(setEnabled(bool)));
    connect(_editors, SIGNAL(replaceAvailable(bool)), ui->actionReplaceAll, SLOT(setEnabled(bool)));

    setAction(_editors, ui->actionOpenFile,     SLOT(openFile()),  "document-open");
    setAction(_editors, ui->actionUndo,         SLOT(undo()),      "edit-undo");
    setAction(_editors, ui->actionRedo,         SLOT(redo()),      "edit-redo");
    setAction(_editors, ui->actionCopy,         SLOT(copy()),      "edit-copy");
    setAction(_editors, ui->actionCut,          SLOT(cut()),       "edit-cut");
    setAction(_editors, ui->actionDelete,       SLOT(del()),       "edit-delete");
    setAction(_editors, ui->actionPaste,        SLOT(paste()),     "edit-paste");
    setAction(_editors, ui->actionSelectAll,    SLOT(selectAll()), "edit-select-all");
    setAction(_editors, ui->actionFindReplace,  SLOT(showFind()),  "edit-find");
    setAction(_editors, ui->actionFindNext,     SLOT(findNext()));
    setAction(_editors, ui->actionFindPrevious, SLOT(findPrevious()));
    setAction(_editors, ui->actionReplace,      SLOT(replace()));
    setAction(_editors, ui->actionReplaceFind,  SLOT(replaceFind()));
    setAction(_editors, ui->actionReplaceFindPrevious,  SLOT(replaceFindPrevious()));
    setAction(_editors, ui->actionReplaceAll,   SLOT(replaceAll()));
    setAction(_editors, ui->actionUppercase,    SLOT(uppercase()));
    setAction(_editors, ui->actionLowercase,    SLOT(lowercase()));
    setAction(_editors, ui->actionCapitalize,   SLOT(capitalize()));
    setAction(_editors, ui->actionCloseFile,    SLOT(closeCurrentEditor()));
    setAction(_editors, ui->actionSave,         SLOT(save()),       "document-save");
}

void PynotoWindow::setAction(QAction *action, const char *slot, const QString & iconName)
{
    setAction(this, action, slot, iconName);
}

void PynotoWindow::setAction(QWidget * reciver, QAction *action, const char *slot, const QString & iconName)
{
    reciver->addAction(action);
    connect(action, SIGNAL(triggered()), reciver, slot);
    if (!iconName.isEmpty())
        action->setIcon(IconProvider::instance()->icon(iconName));
}

void PynotoWindow::onProjectAvailable(bool avail)
{
    if (avail) {
        ui->leftDock->setWindowTitle(_projectManager->project()->name());
        setWindowTitle(_projectManager->project()->name()+" - pyNoto");
        Plugins::Settings::instance()->setLastOpenedProject(_projectManager->project()->filename());
        Plugins::Settings::instance()->setLastUsedWorkspace(_projectManager->project()->workspace());
        Plugins::Settings::instance()->addRecentProjects(_projectManager->project()->filename());
        _editors->setProject(_projectManager->project());
    } else {
        ui->leftDock->setWindowTitle("");
        setWindowTitle("pyNoto");
        _editors->closeAllEditors();
        _editors->setProject(NULL);
    }
}

void PynotoWindow::openProject()
{
    QAction *act = qobject_cast<QAction*>(sender());
    _projectManager.slot("loadProject", Q_ARG(QString, act->data().toString()));
}

void PynotoWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void PynotoWindow::showPreferences()
{
    Plugins::Settings::instance()->showPreferences(this);
}

void PynotoWindow::projectRun()
{
    ui->bottomDoc->modeSelected(ShowRun);
    _projectManager->projectRun(ui->bottomDoc->console());
}

